﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using SimpleNotify.Client.Views;
using SimpleNotify.ClientLibrary;
using SimpleNotify.Client.Controls;

namespace SimpleNotify.Client
{
    public class MainComponent
    {
        private NotifyIcon _notico = null;
        private StatusView _statusView = null;
        private ClientLibrary.Client _wrapper = null;
        private Form _frm = new Form();

        public MainComponent()
        {
            // Create an invisible Form. We need this, or the popup control will not work
            _frm.ShowInTaskbar = false;
            _frm.WindowState = FormWindowState.Minimized;
            _frm.Show();

            _wrapper = new ClientLibrary.Client(Properties.Settings.Default.Server);
            _wrapper.OnNotificationReceived += new EventHandler<ClientLibrary.NewNotificationEventArgs>(_wrapper_OnNotificationReceived);

            CreateTrayIcon();
            CreateContextMenu();
        }

        #region Tray Icon & Context Menu

        private void CreateTrayIcon()
        {
            _notico = new NotifyIcon();
            _notico.Icon = Properties.Resources.HistoryIcon16;
            _notico.Text = "SimpleNotify";
            _notico.Visible = true;
        }

        private void CreateContextMenu()
        {
            _notico.ContextMenuStrip = new ContextMenuStrip();
            _notico.ContextMenuStrip.Name = "ContextMenu";
            _notico.ContextMenuStrip.RenderMode = System.Windows.Forms.ToolStripRenderMode.Professional;
            _notico.ContextMenuStrip.Size = new System.Drawing.Size(153, 70);

            AddItemToContextMenu("Status", Properties.Resources.Info16, new System.EventHandler(StatusClick), false);
            AddSeperatorToContextMenu();
            AddItemToContextMenu("&Exit", Properties.Resources._16_door_in, new System.EventHandler(ExitClick), false);
        }

        private void AddSeperatorToContextMenu()
        {
            ToolStripSeparator item = new ToolStripSeparator();
            item.Name = Guid.NewGuid().ToString();
            item.Size = new System.Drawing.Size(149, 6);
            _notico.ContextMenuStrip.Items.Add(item);
        }

        private void AddItemToContextMenu(string text, System.Drawing.Bitmap image, EventHandler eventHandler, bool boldFont)
        {
            ToolStripMenuItem item = new ToolStripMenuItem();
            item.Image = image;
            item.Name = Guid.NewGuid().ToString();
            item.Size = new System.Drawing.Size(152, 22);
            item.Text = text;
            if (boldFont) item.Font = new System.Drawing.Font(item.Font, System.Drawing.FontStyle.Bold);
            item.Click += eventHandler;
            _notico.ContextMenuStrip.Items.Add(item);
        }

        #endregion

        #region Popup

        private void ShowPopup(NewNotificationEventArgs e)
        {
            int popupHeight = 0;
            PopupControl popup = CreatePopupControl(e, out popupHeight);

            popup.NormalTitleColor = Color.Navy;
            popup.CloseClickable = true;
            popup.EnableSelectionRectangle = false;
            popup.KeepVisibleOnMousOver = true;
            popup.ReShowOnMouseOver = true;
            popup.SetCloseBitmap(Properties.Resources.CloseButton, Color.FromArgb(255, 0, 255), new Point(304, 12));

            // Set the title and text
            if (e.Title.Length > 0)
            {
                popup.TitleRectangle = new Rectangle(50, 9, 200, 25);
                popup.ContentRectangle = new Rectangle(50, 31, 200, popupHeight - 45);
            }
            else
            {
                popup.ContentRectangle = new Rectangle(50, 15, 200, popupHeight - 45);
            }

            // Show popup to the user
            popup.Show(e.Title, e.Text, 500, 15000, 500);
            Application.DoEvents();
        }

        private PopupControl CreatePopupControl(NewNotificationEventArgs e, out int popupHeight)
        {
            PopupControl popup = new PopupControl();

            // Calculate the height for the given text
            Graphics grfx2 = new Control().CreateGraphics();
            SizeF sizef;
            int x, y = 0;
            sizef = grfx2.MeasureString(e.Text, popup.NormalContentFont, 200);
            x = (int)sizef.Width;
            y = (int)sizef.Height;

            // Add some more height for border graphics, so it not looks squeezed
            popupHeight = y + 50;

            // Create Background image depending on notification type and needed popup height
            Bitmap background = CreateBackgroundImage(e.Type, popupHeight);
            popup.SetBackgroundBitmap(background, Color.Pink);

            return popup;
        }

        private Bitmap CreateBackgroundImage(NotificationType notificationType, int Height)
        {
            Bitmap background = new Bitmap(329, Height);
            using (Graphics grfx = Graphics.FromImage(background))
            {
                grfx.DrawImage(new Bitmap(Properties.Resources.BackgroundTop, new Size(329, 8)), 0, 0);
                grfx.DrawImage(new Bitmap(Properties.Resources.BackgroundMiddle, new Size(Properties.Resources.BackgroundMiddle.Width, Height - 8 - 4)), 0, 8);
                if (notificationType != NotificationType.None) grfx.DrawImage(new Bitmap(GetImageByType(notificationType), new Size(32, 32)), 13, 14);
                grfx.DrawImage(new Bitmap(Properties.Resources.BackgroundBottom, new Size(329, 4)), 0, Height - 4);
            }
            return background;
        }

        private Image GetImageByType(NotificationType notificationType)
        {
            Image retValue = null;
            switch (notificationType)
            {
                case NotificationType.Confirmation:
                    retValue = Properties.Resources.Ok;
                    break;
                case NotificationType.Warning:
                    retValue = Properties.Resources.Warning;
                    break;
                case NotificationType.Error:
                    retValue = Properties.Resources.Error;
                    break;
                case NotificationType.Information:
                    retValue = Properties.Resources.Info;
                    break;
             }
            return retValue;
        }

        #endregion

        #region Events

        public void _wrapper_OnNotificationReceived(object sender, ClientLibrary.NewNotificationEventArgs e)
        {
            _frm.BeginInvoke(new MethodInvoker(delegate()
            {
                ShowPopup(e);
            }));
        }

        private void StatusClick(Object sender, EventArgs e)
        {
            if (_statusView != null && _statusView.IsHandleCreated)
            {
                _statusView.Activate();
            }
            else
            {
                _statusView = new StatusView(_wrapper);
                _statusView.Show();
            }
        }

        private void ExitClick(Object sender, EventArgs e)
        {
            _notico.Dispose();
            Application.Exit();
        }

        #endregion
    }
}
